package com.gradumate.server.service;

import java.util.ArrayList;
import java.util.TreeMap;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.gradumate.client.service.GraduMateService;
import com.gradumate.server.MailCommunicator;
import com.gradumate.server.PMF;
import com.gradumate.server.alfresco.ContentBeheer;
import com.gradumate.server.alfresco.FolderContent;
import com.gradumate.server.alfresco.TicketService;
import com.gradumate.server.dao.Gebruiker_DAO;
import com.gradumate.server.dao.LoginToken_DAO;
import com.gradumate.server.dao.VerleenToegang_DAO;
import com.gradumate.shared.FormulierInfo;
import com.gradumate.shared.Gebruiker;
import com.gradumate.shared.LoginToken;
import com.gradumate.shared.VerleenToegang;

/**
 * Klasse die met de client communiceert.
 * 
 * @author IJsbrand
 * 
 */
@SuppressWarnings("serial")
public class GraduMateServer extends RemoteServiceServlet implements
		GraduMateService {

	// Datastore
	private final Gebruiker_DAO gebruikerDAO = new Gebruiker_DAO();
	private final VerleenToegang_DAO toegangDAO = new VerleenToegang_DAO();
	private final LoginToken_DAO loginTokenDAO = new LoginToken_DAO();
	private ContentBeheer content;

	// Logger
	@SuppressWarnings("unused")
	private final Logger log = Logger.getLogger(GraduMateServer.class.getName());
	
	// SiteListing
	private FolderContent siteFetchService;

	/**
	 * Haalt een Gebruiker object op a.d.v zijn e-mail en haalt een ticket op voor de Gebruiker
	 * 
	 * @param String
	 *            email met het emailadres van de Gebruiker
	 * @return gevonden Gebruiker anders null.
	 */
	public Gebruiker getGebruikerByEmail(String email) {
		Gebruiker g = gebruikerDAO.getGebruikerByEmail(email);
		if(g.getType() == 1){
			g.setTicket(TicketService.getGebruikerTicket(g));
		}
		return g;
	}

	/**
	 * Haalt alle Gebruiker objecten op
	 * 
	 * @return ArrayList<Gebruiker> met Gebruiker objecten
	 */
	public ArrayList<Gebruiker> getGebruikers() {
		return gebruikerDAO.getGebruikers();
	}

	/**
	 * Haalt Gebruiker objecten op a.d.v type
	 * 
	 * @param Integer
	 *            met type
	 * @return gevonden Gebruiker objecten
	 * @see com.gradumate.server.dao.Gebruiker_DAO;
	 */
	public ArrayList<Gebruiker> getGebruikerByType(int type) {
		return gebruikerDAO.getGebruikerByType(type);
	}

	/**
	 * Roept de methode addGebruiker aan in de klasse gebruikerDAO en stuurt een
	 * gebruiker object mee<br>
	 * 
	 * @param g
	 *            Gebruiker object
	 */
	public Boolean addGebruiker(Gebruiker g, int type) {
		boolean result = false;
		
		content = new ContentBeheer();
		
		if (type == Gebruiker.TYPE_STUDENT){ //type 1 is de student
			if (content.addAlfrescoStudent(g) && gebruikerDAO.addGebruiker(g)){
				result = true;
			}
		}
		else if(gebruikerDAO.addGebruiker(g)){
			result = true;
		}
		return result;
	}
	
	/**
	 * Update een Gebruiker object
	 * @param Gebruiker gebruiker die geupdate gaat worden
	 * @return true wanneer gelukt
	 */
	public Boolean updateGebruiker(Gebruiker gebruiker) {
		return gebruikerDAO.updateGebruiker(gebruiker).equals(gebruiker);
	}

	/**
	 * Haalt een Gebruiker op a.d.v. zijn studentnummer
	 * 
	 * @param int studentNummer van de Gebruiker
	 * @return gevonden Gebruiker anders null
	 */
	public Gebruiker getGebruikerByStudentnummer(int studentNummer) {
		return gebruikerDAO.getGebruikerByStudentnummer(studentNummer);
	}

	/**
	 * Verleent een Gebruiker toegang tot het systeem a.d.v zijn studentnummer
	 * 
	 * @param int studentnummer van de Gebruiker
	 * @return true wanneer gelukt, anders false
	 */
	public Boolean verleenToegang(int studentNummer) {
		// Gebruiker bepalen a.d.v. zijn studentnummer
		Gebruiker g = gebruikerDAO.getGebruikerByStudentnummer(studentNummer);
		if (g != null) {
			// Toegang verlenen
			VerleenToegang vt = new VerleenToegang(studentNummer);
			return toegangDAO.addVerleenToegang(vt);
		} else {
			return false;
		}
	}
	
	/**
	 * Controlleerd of de student de toegang tot het systeem verleend heeft gekregen
	 * @param Gebruiker student die gecontroleerd word
	 * @return true wanneer wel, false wanneer niet
	 */
	public boolean hasToegangVerleent(Gebruiker student) {
		return toegangDAO.getVerleenToegang(student.getStudentNummer()) != null;
	}
	
	/**
	 * Haalt een overzichtslijst op met de nog in te beoordelen ingediende afstudeervoorstellen
	 * @param ArrayList<Site> met nog te beoordelen ingediende afstudeervoostellen
	 */
	public ArrayList<Gebruiker> getAfstudeerVoorstelOverzicht() {
		siteFetchService = new FolderContent();
		return siteFetchService.getOnbeoordeeldeAfstudeerVoorstellen();
	}
	
	/**
	 * Haalt een overzichtslijst op met de nog in te beoordelen ingediende afstudeervoorstellen
	 * @param ArrayList<Site> met nog te beoordelen ingediende afstudeervoostellen
	 */
	public ArrayList<Gebruiker> getAfstudeerVerzoekOverzicht() {
		siteFetchService = new FolderContent();
		return siteFetchService.getOnbeoordeeldeAfstudeerVerzoeken();
	}

	/**
	 * Deze methode krijgt alle parameters binnen vanaf de client. In de
	 * toekomst zal hier de informatie doorgestuurd worden naar Alfresco.<br>
	 * 
	 * @param naam
	 *            De naam van het bedrijf die je hebt opgegeven.
	 * @param voertaal
	 *            De voertaal van het bedrijf die je hebt opgegeven.
	 * @param gebouw
	 *            De naam die je hebt opgegeven van het gebouw van het bedrijf.
	 * @param straatnaam
	 *            De straatnaam die je hebt opgegeven van het bedrijf.
	 * @param huisnr
	 *            Het huisnummer dat je hebt opgegeven van het bedrijf.
	 * @param postcode
	 *            De postcode die je hebt opgegeven van het bedrijf.
	 * @param plaats
	 *            De plaats die je hebt opgegeven van het bedrijf.
	 * @param website
	 *            De website die je hebt opgegeven van het bedrijf.
	 * @param extra
	 *            De extra informatie die je hebt opgegeven van het bedrijf.
	 * @param werknemers
	 *            Het aantal werknemers van het bedrijf wat je hebt opgegeven.
	 * @param file
	 *            Het afstudeervoorstel die je geupload hebt.
	 * @param radiobutton
	 *            Het soort praktijkopdracht dat je gaat uitvoeren.
	 * @param startdatum
	 *            De startdatum van je praktijkopdracht.
	 * @param einddatum
	 *            De einddatum van je eindopdracht.
	 * @param onderwerp
	 *            Het onderwerp van je praktijkopdracht.
	 * @param aantalstudenten
	 *            Het maximaal aantal te plaatsen afstuderende studenten bij het
	 *            bedrijf.
	 * @param vergoeding
	 *            De bruto vergoeding van de afstuderende student.
	 */
	public void voorstelIndienen(String naam, String voertaal, String gebouw,
			String straatnaam, String huisnr, String postcode, String plaats,
			String website, String extra, String werknemers, String file,
			String radiobutton, String startdatum, String einddatum,
			String onderwerp, String aantalstudenten, String vergoeding) {
	}
	
	/**
	 * Haalt de LoginTicket uit de DS die hoort bij een token & gebruikerEmail
	 * @param String token waarop gezocht word
	 * @param String gebruikerEmail waarop gezocht word
	 * @return gevonden LoginToken
	 */
	public LoginToken getLoginTokenByTokenAndEmail(String token, String gebruikerEmail) {
		return loginTokenDAO.getLoginTokenByTokenAndEmail(token, gebruikerEmail);
	}
	
	/**
	 * Verwijderd een LoginToken uit de Datastore
	 * @param LoginToken loginToken de token die verwijderd moet worden
	 * @return
	 */
	public Boolean deleteLoginToken(LoginToken loginToken) {
		return loginTokenDAO.deleteLoginToken(loginToken);
	}
	
	/**
	 * Stuurt de beoordeling van het verzoek terug naar de Alfresco server
	 * @param Gebruiker de student die beoordeeld word
	 * @param Gebruiker de studieadviseur die de beoordeling heeft gedaan
	 * @param boolean beoordeling
	 * @param String motivatie
	 * @param callback
	 */
	public Boolean setAfstudeerVerzoekBeoordeling(Gebruiker student, Gebruiker studieAdviseur, boolean beoordeling, String motivatie) {
		// ContentBeheer verversen.
		content = new ContentBeheer();
		
		// Return boolean
		boolean r = false;
		
		// Mailtje sturen naar de student
		r = MailCommunicator.sendAfstudeerVerzoekBeoordelingEmailStudent(student, studieAdviseur, beoordeling, motivatie);
		
		// Verplaats bestand naar Inbehandeling map
		content.verplaatsAfstudeerVerzoek(student, beoordeling);
		
		if (beoordeling) {
			// Faculteit, Instituut, Opleiding bepalen
			String faculteit = student.getFaculteit();
			String instituut = student.getInstituut();
			String opleiding = student.getOpleiding().get(0); // gezien het een student is is get(0) altijd gevuld.
			ArrayList<Gebruiker> commissieleden = gebruikerDAO.getLedenAfstudeerCommissieByFaculteitInstituutAndOpleiding(faculteit, instituut, opleiding);
			
			// Mailtje sturen naar afstudeercommissie
			r = MailCommunicator.sendAfstudeerVerzoekBeoordelingEmailCommissie(student, commissieleden, studieAdviseur);
		}
		return r;
	}
	
	/**
	 * Stuurt de beoordeling van het voorstel terug naar de Alfresco server
	 * @param Gebruiker de student die beoordeeld word
	 * @param Gebruiker de commissielid die de beoordeling heeft gedaan
	 * @param boolean beoordeling
	 * @param String motivatie
	 * @param callback
	 */
	public Boolean setAfstudeerVoorstelBeoordeling(Gebruiker student, Gebruiker commissieLid, boolean beoordeling, String motivatie) {
		// Contentbeheer verversen
		content = new ContentBeheer();
		
		// Return boolean
		boolean r = false;
		
		// Mailtje sturen naar de student
		r = MailCommunicator.sendAfstudeerVoorstelBeoordelingEmailStudent(student, commissieLid, beoordeling, motivatie);
		
		// Verplaats bestand naar Goedgekeurd map
		content.verplaatsAfstudeerVoorstel(student, beoordeling, motivatie);
		
		return r;
	}
	
	/**
	 * Haalt een hashmap op met daarin de waarde die bij een KPI horen van een bepaald gebruikertype.
	 * @return HashMap<String, Integer> met daarin Index => Waarde.
	 */
	public TreeMap<String, Integer> getKpiWaarde(int gebruikerType) {
		
		TreeMap<String, Integer> data = new TreeMap<String, Integer>();
		FolderContent fc = new FolderContent();
		
		if (gebruikerType == Gebruiker.TYPE_STUDIE_ADVISEUR) {
			data.put("onbeoordeeld", fc.getTotaalAantalOnbeoordeeldeAfstudeerVerzoeken());
			//data.put("beoordeeld", fc.getTotaalAantalBeoordeeldeAfstudeerVerzoeken());
			data.put("goedgekeurd", fc.getTotaalAantalGoedGekeurdeAfstudeerVerzoeken());
			data.put("afgekeurd", fc.getTotaalAantalAfgekeurdeAfstudeerVerzoeken());
			data.put("totaal", fc.getTotaalAantalContentItems());
		} else if (gebruikerType == Gebruiker.TYPE_AFSTUDEERCOMMISSIE_LID) {
			data.put("onbeoordeeld", fc.getTotaalAantalOnBeoordeeldeAfstudeerVoorstellen());
			//data.put("beoordeeld", fc.getTotaalAantalBeoordeeldeAfstudeerVerzoeken());
			data.put("goedgekeurd", fc.getTotaalAantalGoedGekeurdeAfstudeerVoorstellen());
			data.put("afgekeurd", fc.getTotaalAantalAfgekeurdeAfstudeerVoorstellen());
			data.put("totaal", fc.getTotaalAantalAfstudeerVoorstellen());
		} else if (gebruikerType == Gebruiker.TYPE_TEAMLEIDER_PERSONEELSZAKEN) {
			data.put("totaalstudenten", gebruikerDAO.getStudenten().size());
			data.put("goedgekeurd", fc.getTotaalAantalGoedGekeurdeAfstudeerVoorstellen());
			data.put("inbehandeling", fc.getTotaalAantalOnbeoordeeldeAfstudeerVerzoeken() + fc.getTotaalAantalOnBeoordeeldeAfstudeerVoorstellen());
		}
		
		return data;
	}
	
	/**
	 * Maakt het object persistent wat alle informatie bevat die de student heeft ingevuld in het webformulier
	 */
	public FormulierInfo setFormulier(FormulierInfo info) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try{
			pm.makePersistent(info);
			log.info("product wordt opgeslagen");
		}
		catch(Exception e){
			System.out.println("fout: " + e.getMessage());
			log.severe("product wordt niet opgeslagen");
		}
		finally{
			pm.close();
		}
		return info;
	}
	
	/**
	 * Haalt de status op van het afstudeervoorstel van de student.
	 * @param Gebruiker student waar de controle voor word uitgevoerd
	 * @return TreeMap<String, Boolean> met daarin diverse true/false waarden
	 */
	public TreeMap<String, Boolean> getStatusAfstudeerVoorstelStudent(Gebruiker student) {
		
		TreeMap<String, Boolean> status = new TreeMap<String, Boolean>();
		FolderContent fc = new FolderContent();
		
		// Alle inhoud bepalen
		// Wanneer inbehandeling true is dan staat er een document in de map in behandeling.
		status.put("afgekeurd", !fc.getStudentAfgekeurdVoorstellen(student).isEmpty());
		status.put("goedgekeurd", !fc.getStudentGoedgekeurdeVoorstellen(student).isEmpty());
		status.put("concept", !fc.getStudentConceptVoorstellen(student).isEmpty());
		status.put("inbehandeling", !fc.getStudentInBehandelingVoorstellen(student).isEmpty());
		
		return status;
	}
	
	/**
	 * Methode die het afstudeervoorstel opent van de student in de browser. De actie die meegegeven wordt kan 'open'
	 * zijn of 'download'
	 */
	public String openDocument(Gebruiker student) {
		content = new ContentBeheer();
		String url = content.openDocument(student);
		return url;
	}

	@Override
	public String toonVoortgang() {
		content = new ContentBeheer();
		String url = content.toonVoortgang();
		return url;
	}
}
